#include <QObject>
#include <QDebug>
#include "qtsoap\src\qtsoap.h"
#include "tagdatarequest.h"
#include "participant.h"

TagDataRequest::TagDataRequest(QObject *parent) :
    QObject(parent),
    tagData(NULL),
    activityData(NULL),
    http(this)
{
    QObject::connect(&http, SIGNAL(responseReady()), SLOT(getResponse()));
}
/*
void TagDataRequest::processTag(Participant *tagObj)
{
    QObject::connect(this, SIGNAL(updateTag(Participant::TagType,QString,Participant::ParticipantStatusType)), tagObj, SLOT(setData(Participant::TagType,QString,Participant::ParticipantStatusType)));
    qDebug() << "Function getTagData for UID " << tagObj->getTagId();
    currentRequest = "";
    getTagData();
}

void TagDataRequest::processTag(Participant *tagObj, Participant *statusChangeObj)
{
    QObject::connect(this, SIGNAL(updateTag(Participant::TagType,QString,Participant::StatusType)), tagObj, SLOT(setData(Participant::TagType,QString,Participant::StatusType)));
    qDebug() << "Function getTagData for UID " << tagObj->getTagId()  << "Update UID " << statusChangeObj->getTagId();
    currentRequest = "";
    getTagData();
}
*/
void TagDataRequest::processTag(QByteArray tagId, QByteArray activityId, QDateTime time)
{
    tagData = new Participant(this, tagId.toHex(), time);
    QObject::connect(this, SIGNAL(updateTag(QString,QString,QString)), tagData, SLOT(setData(QString,QString,QString)));
    currentRequest = "";
    activityTagId = activityId;
    getTagData();
}

void TagDataRequest::processTag(QByteArray tagId, QByteArray activityId, QDateTime time, QByteArray selectedTagId)
{
    tagData = new Participant(this, tagId.toHex(), time);
    QObject::connect(this, SIGNAL(updateTag(QString,QString,QString)), tagData, SLOT(setData(QString,QString,QString)));
    manualChangedId = selectedTagId;
    currentRequest = "";
    activityTagId = activityId;
    getTagData();
}

void TagDataRequest::getTagData()
{
    /* TODO: Prepare network package */
    QtSoapMessage message;
    QByteArray uid = tagData->getTagId();
    QString strUID(uid);
    message.setMethod("GetTagData", "http://spmobil.datagiraffen.dk/");
    message.addBodyItem(new QtSoapSimpleType(QtSoapQName("TagUID"), strUID));
//    qDebug() << message.toXmlString(4);
    http.setAction("http://spmobil.datagiraffen.dk/GetTagData");
    http.setHost("spmobil.datagiraffen.dk");
    currentRequest = "GetTagData";
    http.submitRequest(message, "spmobil.asmx");
}

void TagDataRequest::handleGetTagDataResp(const QtSoapType& res)
{
    Participant::TagType participantType;
    QString name;
    Participant::StatusType participantStatus;
    qDebug() << "GetTagData";
    qDebug() << "Name: " << res["Name"].toString();
    qDebug() << "TagUID: " << res["TagUID"].toString();
    qDebug() << "UIDStatus: " << res["UIDStatus"].toString();
    qDebug() << "Type: " << res["Type"].toString();
    qDebug() << "Status: " << res["Status"].toString();
    if(res["UIDStatus"].toString() == "Known")  {
        emit updateTag(res["Type"].toString(), res["Name"].toString(), res["Status"].toString());
        tagDataReady();
    }
    else    {
        qDebug() << "TagUID is Unknown or Unexpected.";
        emit updateActivityParticipent(NULL);
        delete tagData;
    }
}

void TagDataRequest::scannedTagData(bool manualCheckIn)
{
    /* TODO: Prepare network package */
    QtSoapMessage message;
    QDateTime datetime = QDateTime::currentDateTime();
    QByteArray uid = tagData->getTagId();
    QString strTagUid(uid);
    QString strActivityUid(activityTagId);
    message.setMethod("ScannedTagData", "http://spmobil.datagiraffen.dk/");
    message.addBodyItem(new QtSoapSimpleType(QtSoapQName("TransmissionTime"), QDateTime::currentDateTime()));
    message.addBodyItem(new QtSoapSimpleType(QtSoapQName("ActivityUID"), strActivityUid));
    message.addBodyItem(new QtSoapSimpleType(QtSoapQName("TagUID"), strTagUid));
    message.addBodyItem(new QtSoapSimpleType(QtSoapQName("ScanTime"), tagData->getScanTime()));
    if(manualCheckIn)
        message.addBodyItem(new QtSoapSimpleType(QtSoapQName("CheckIn"), QString("Manual")));
    else
        message.addBodyItem(new QtSoapSimpleType(QtSoapQName("CheckIn"), QString("NfcTag")));

//    qDebug() << message.toXmlString(4);
    http.setAction("http://spmobil.datagiraffen.dk/ScannedTagData");
    http.setHost("spmobil.datagiraffen.dk");
    currentRequest = "ScannedTagData";
    http.submitRequest(message, "spmobil.asmx");
}

void TagDataRequest::handleScannedTagDataResp(const QtSoapType& res)
{
    qDebug() << "ScannedTagData";
    qDebug() << "Name: " << res["Name"].toString();
    qDebug() << "TagUID: " << res["TagUID"].toString();
    qDebug() << "UIDStatus: " << res["UIDStatus"].toString();
    qDebug() << "Tape: " << res["Type"].toString();
    qDebug() << "Status: " << res["Status"].toString();
    if(res["UIDStatus"].toString() == "Known" || res["UIDStatus"].toString() == "Unexpected")    {  // Get unexpected even if participant is part of the list
            emit updateActivityParticipent(tagData);
    }
    else    {
        qDebug() << "TagUID is Unknown or Unexpected.";
        emit updateActivityParticipent(NULL);
    }
    delete tagData;
    manualChangedId.clear();
}


void TagDataRequest::getActivityData()
{
    /* TODO: Prepare network package */
    QtSoapMessage message;
    QDateTime datetime = QDateTime::currentDateTime();
    QByteArray uid = tagData->getTagId();
    QString strUid(uid);
    message.setMethod("GetActivityData", "http://spmobil.datagiraffen.dk/");
    message.addBodyItem(new QtSoapSimpleType(QtSoapQName("TransmissionTime"), QDateTime::currentDateTime()));
    message.addBodyItem(new QtSoapSimpleType(QtSoapQName("TagUID"), strUid));
//    qDebug() << message.toXmlString(4);
    http.setAction("http://spmobil.datagiraffen.dk/GetActivityData");
    http.setHost("spmobil.datagiraffen.dk");
    currentRequest = "GetActivityData";
    http.submitRequest(message, "spmobil.asmx");
}

void TagDataRequest::handleGetActivityDataResp(const QtSoapType& res)
{
    qDebug() << "GetActivityData";
    qDebug() << "Name: " << res["ActivityName"].toString();
    qDebug() << "Start time: " << res["StartTime"].toString();
    qDebug() << "Stop time: " << res["EndTime"].toString();
    qDebug() << "Timeout: " << res["RegistrationTimeout"].toInt();
    QString name;
    QString timeTmp;
    QDateTime startTime;
    QDateTime stopTime;
    QByteArray uid;
    int timeout;
    name = res["ActivityName"].toString();
    timeTmp = res["StartTime"].toString();
    startTime = QDateTime::fromString(timeTmp, "yyyy-MM-ddTHH:mm:ss");
    timeTmp = res["EndTime"].toString();
    stopTime = QDateTime::fromString(res["EndTime"].toString(), "yyyy-MM-ddTHH:mm:ss");
    timeout = res["RegistrationTimeout"].toInt();
    uid = res["ActivityUID"].toString().toAscii();
    emit updateActivity(tagData, uid, name, startTime, stopTime, timeout);
    const QtSoapType &resultElements = res["ParticipantArray"];

    qDebug() << "----------------------------------------------";
    qDebug() << resultElements.count();
    qDebug() << "----------------------------------------------";
    for (int i = 0; i < resultElements.count(); ++i) {
        const QtSoapType &resultElement = res["ParticipantArray"][i];
        qDebug() << "----------------------------------------------";
        Participant p(resultElement["TagUID"].toString(), resultElement["Type"].toString(), resultElement["Name"].toString(), resultElement["Status"].toString());
        if(p.getTagType() == Participant::Paricipant)  {
            emit participantAdd(&p);
        }
    }
    emit participantAdd(NULL);
    activityDataReady();
}

void TagDataRequest::registrationComplete(QByteArray activityUid)
{
    /* TODO: Prepare network package */
    QtSoapMessage message;
    QDateTime datetime = QDateTime::currentDateTime();
    QByteArray uid = tagData->getTagId();
    QString strUid(activityUid);
    message.setMethod("RegistrationComplete", "http://spmobil.datagiraffen.dk/");
    message.addBodyItem(new QtSoapSimpleType(QtSoapQName("TransmissionTime"), QDateTime::currentDateTime()));
    message.addBodyItem(new QtSoapSimpleType(QtSoapQName("ActivityUID"), strUid));
//    qDebug() << message.toXmlString(4);
    http.setAction("http://spmobil.datagiraffen.dk/GetActivityData");
    http.setHost("spmobil.datagiraffen.dk");
    currentRequest = "RegistrationComplete";
    http.submitRequest(message, "spmobil.asmx");
}

void TagDataRequest::getResponse()
{
    qDebug() << "Respose received";
    const QtSoapMessage &resp = http.getResponse();
//    qDebug() << resp.toXmlString(4);
    if (resp.isFault()) {
        qDebug() << "Soap fault";
//        Q_ASSERT(true);
        emit activityUpdatedSignal(Activity::NetworkError);
        delete tagData;
        manualChangedId.clear();
        return;
    }
    const QtSoapType &res = resp.returnValue();
    if (!res.isValid()) {
        qDebug() << "Response invalid";
//        Q_ASSERT(true);
        emit activityUpdatedSignal(Activity::NetworkError);
        delete tagData;
        manualChangedId.clear();
        return;
    }

    if(currentRequest == "GetTagData")    {
        handleGetTagDataResp(res);
    }
    else if(currentRequest == "ScannedTagData") {
        handleScannedTagDataResp(res);
    }
    else if(currentRequest == "GetActivityData")    {
        handleGetActivityDataResp(res);
    }
    else if(currentRequest == "RegistrationCompleteResponse")   {
        qDebug() << "RegistrationComplete";
    }
    else    {
        qDebug() << "Method not found";
//        Q_ASSERT(true);
    }
}

void TagDataRequest::tagDataReady()
{
        if(tagData->getTagType() == Participant::Organiser)   {
            if(manualChangedId > 0) {
                emit activityOrganiserSignal(tagData, manualChangedId);
                delete tagData;
                manualChangedId.clear();
            }
            else    {
                getActivityData();
            }
        }
        else if(tagData->getTagType() == Participant::Paricipant && manualChangedId <= 0)   {
            scannedTagData(false);
        }
        else    {
            scannedTagData(false);
        }
}

void TagDataRequest::activityDataReady()
{
    emit activityUpdatedSignal(Activity::ActivityFound);
    manualChangedId.clear();
    delete tagData;
}
